<?php

namespace jx\model;

/*model 基类*/

use PDO;

class base
{
    //表名
    private $table;
    //PDO
    private static $pdo = null;
    //where条件
    private $where = '';
    //排序
    private $order = '';

    //实例化首先加载配置项 和 表名
    public function __construct($config, $table)
    {
        $this->table = $table;
        $this->connect($config);
    }

    //链接数据库
    private function connect($config)
    {
        //$pdo不为空时候说明已经实例化过，无需再次实例化。 防止多次实例化
        if (!is_null(self::$pdo)) {
            return;
        }
        /*通过PDO链接数据库*/
        try {
            $dsn = "mysql:host={$config['host']};dbname={$config['dbname']}";
            $user = $config['user'];
            $pass = $config['pass'];
            $pdo = new PDO($dsn, $user, $pass);
            //设置错误类型
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            //设置编码
            $pdo->query("SET NAMES " . $config['db_charset']);
            //将pdo设置为静态方法
            self::$pdo = $pdo;
        } catch (PDOException $e) {
            //抛出错误
            die($e->getMessage());
        }
    }

    /*----------------------------排序-----------------------------------------*/
    public function order($order)
    {
        if (empty($order)) {
            $this->order = ' ';
        } else {
            $this->order = " ORDER BY {$order} ";
        }
        return $this;
    }

    /*----------------------------查询-----------------------------------------*/
    //统一查询方法
    private function query($sql)
    {
        try {
            $result = self::$pdo->query($sql);
            $data = $result->fetchAll(PDO::FETCH_ASSOC);
            return $data;
        } catch (PDOException $e) {
            //抛出错误
            die($e->getMessage());
        }
    }

    //where条件
    public function where($where)
    {
        if (empty($where)) {
            $this->where = ' ';
        } else {
            $this->where = " WHERE {$where} ";
        }
        return $this;
    }

    //获取全部数据
    public function get($count='')
    {
        $limitCol = $count == '' ? '' : " LIMIT {$count} ";

        $sql = "select * from {$this->table} {$this->where} {$this->order} {$limitCol}";
        $data = $this->query($sql);
        return $data;
    }

    //根据主键获取数据
    public function find($id = '')
    {
        if (empty($id)) {
            return '主键不能为空';
        }
        //获取主键
        $priKey = $this->getPriKey();
        $this->where = " WHERE {$priKey}={$id} ";
        $data = $this->get()[0];
        return $data;
    }

    //查询数据表的主键
    private function getPriKey()
    {
        $sql = "desc {$this->table}";
        $datas = $this->query($sql);
        //声明主键变量
        $priId = '';
        foreach ($datas as $data) {
            if ($data['Key'] == 'PRI') {
                $priId = $data['Field'];
                break;
            }
        }
        return $priId;
    }

    /*----------------------------执行-----------------------------------------*/

    //统一执行方法
    private function exec($sql)
    {
        try {
            $resRows = self::$pdo->exec($sql);
            if ($lastInsertId = self::$pdo->lastInsertId()) {
                //如果插入 返回上一次插入的id值
                return $lastInsertId;
            }
            //返回影响的行数
            return $resRows;
        } catch (PDOException $e) {
            //抛出错误
            die($e->getMessage());
        }
    }

    /*----------------------------删除-----------------------------------------*/
    //删除 传入删除的条数 默认全部;
    public function delete($count = '')
    {
        if ($this->where == '') {
            return '条件为空，禁止删除';
        }
        $limitCol = $count == '' ? '' : " LIMIT {$count} ";
        $sql = "DELETE FROM {$this->table} {$this->where}  {$this->order} $limitCol;";
        return $this->exec($sql);
    }

    /*----------------------------插入-----------------------------------------*/
    //插入和更新数据 有where 则更新 没有where 则插入
    public function save($data = [])
    {
        if (empty($data) || !is_array($data)) {
            return '数据不能为空或数据类型错误';
        }
        $tableColu = $this->getAllColu();
        //根据传入进来的数据 进行过滤插入
        //1.获取有效字段
        $colArr = [];
        $colKeyArr = [];
        $colValArr = [];
        foreach ($data as $key => $v) {
            if (in_array($key, $tableColu)) {
                $colKeyArr[] = $key;
                $colValArr[] = $v;
                $colArr[$key] = $v;
            }
        }
        /*判断where是否为空 空的话插入 否者更新数据*/
        if ($this->where != '') {
            //2.预处理的SQL语句
            $preColKey = '';
            foreach ($colKeyArr as $key => $preColKeyArr) {
                $preColKey .= $preColKeyArr . '=?,';
            }
            $preColKey = trim($preColKey, ',');
            $sql = "UPDATE {$this->table} SET {$preColKey} {$this->where} ";
        } else {
            //2.预处理的SQL语句
            $keyStr = implode(',', $colKeyArr);
            $valStr = trim(str_repeat('?,', count($colValArr)), ',');
            $sql = "insert into {$this->table}({$keyStr}) values({$valStr})";   // ?号的方式
        }


        $stmt = self::$pdo->prepare($sql);
        //3.绑定数据
        foreach ($colValArr as $key => $v) {
            $stmt->bindValue($key + 1, $v);
        }
        $stmt->execute();
        return $stmt->rowCount();  //返回受影响的行数
    }

    //插入多条数据 传入二维数组
    public function saveAll($datas = [])
    {
        $affceCol = 0;
        foreach ($datas as $data) {
            $affceCol += $this->save($data);
        }
        return $affceCol;
    }

    //获取数据表所有的列 返回除了主键之外的数组数据
    private function getAllColu()
    {
        $sql = " select COLUMN_NAME from information_schema.COLUMNS where table_name = '{$this->table}'";
        $data = $this->query($sql);
        $allColu = [];
        foreach ($data as $col) {
            if ($col['COLUMN_NAME'] != $this->getPriKey()) {
                $allColu[] = $col['COLUMN_NAME'];
            }
        }
        return $allColu;
    }
}

























